from flask import Blueprint, render_template, request, redirect, url_for, current_app
from app.models import User, Crawler, Tag, Category
from app.forms import CrawlerEditForm, UserEditForm, CategoryForm, LoginForm
from app.extensions import db, scheduler
from app.utils import redirect_back, random_filename
import os
from app.engine.rss_common import feed_handler
from app.decorators import admin_required
from flask_login import current_user, login_user


admin_bp = Blueprint('admin', __name__)


@admin_bp.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('.index'))
    form = LoginForm()
    if form.validate_on_submit():
        email = form.email.data
        password = form.password.data
        user = User.query.filter_by(email=email).first()
        if user:
            if email == user.email and user.validate_password(password):
                login_user(user)
                return redirect(url_for('.index'))
    return render_template('admin/login.html', form=form)


@admin_bp.route('/')
@admin_required
def index():
    return render_template('admin/index.html')


@admin_bp.route('/user')
@admin_required
def user():
    users = User.query.all()
    form = UserEditForm()
    return render_template('admin/user.html', users=users, form=form)


@admin_bp.route('/crawler')
@admin_required
def crawler():
    page = request.args.get('page', 1, type=int)
    pagination = Crawler.query.order_by(Crawler.id).paginate(page, per_page=20)
    crawlers = pagination.items
    return render_template('admin/crawler.html', crawlers=crawlers, pagination=pagination)


@admin_bp.route('/crawler/add', methods=['GET', 'POST'])
@admin_required
def crawler_add():
    form = CrawlerEditForm()
    if form.validate_on_submit():
        f = form.image.data
        img_filename = random_filename(f.filename)
        f.save(os.path.join(os.path.join(current_app.config['CRAWLER_PIC']), img_filename))
        cra = Crawler(name=form.name.data, category_id=form.category.data, rate=form.rate.data, type=form.type.data,
                      source=form.source.data, slug=form.slug.data, describe=form.describe.data, image=img_filename)
        for name in form.tag.data.split():
            tag = Tag.query.filter_by(name=name).first()
            if tag is None:
                tag = Tag(name=name)
                db.session.add(tag)
                db.session.commit()
                cra.tags.append(tag)
        db.session.add(cra)
        db.session.commit()
        job = scheduler.add_job(id=cra.name, func=feed_handler, trigger='interval', seconds=cra.rate, args=[cra.id])
        return redirect(url_for('admin.crawler'))
    return render_template('admin/crawler_edit.html', form=form)


@admin_bp.route('/crawler/edit/<crawler_id>', methods=['GET', 'POST'])
@admin_required
def crawler_edit(crawler_id):
    form = CrawlerEditForm()
    cra = Crawler.query.get_or_404(crawler_id)
    if form.validate_on_submit():
        f = form.image.data
        img_filename = random_filename(f.filename)
        f.save(os.path.join(os.path.join(current_app.config['CRAWLER_PIC']), img_filename))
        cra.image = img_filename
        cra.name = form.name.data
        cra.category_id = form.category.data
        cra.rate = form.rate.data
        cra.slug = form.slug.data
        cra.source = form.source.data
        cra.type = form.type.data
        cra.describe = form.describe.data
        db.session.commit()
        old_job = scheduler.get_job(cra.id)
        if old_job:
            old_job.update_job(trigger='interval', seconds=cra.rate, args=[cra.id])
        return redirect(url_for('.crawler'))
    form.name.data = cra.name
    form.category.data = cra.category_id
    form.rate.data = cra.rate
    form.slug.data = cra.slug
    form.source.data = cra.source
    all_tags = ''
    for tag in cra.tags:
        all_tags += tag.name + ' '
    form.tag.data = all_tags.rstrip()
    form.type.data = cra.type
    form.describe.data = cra.describe
    return render_template('admin/crawler_edit.html', form=form, cra=cra)


@admin_bp.route('/crawler/delete/<int:crawler_id>', methods=['POST'])
@admin_required
def crawler_delete(crawler_id):
    cra = Crawler.query.get_or_404(crawler_id)
    old_job = scheduler.get_job(id=cra.name)
    if old_job:
        scheduler.remove_job(id=cra.name)
    db.session.delete(cra)
    db.session.commit()
    return redirect_back()


@admin_bp.route('/crawler/run/<int:crawler_id>')
@admin_required
def crawler_run(crawler_id):
    cra = Crawler.query.get_or_404(crawler_id)
    scheduler.run_job(id=cra.name)
    return redirect(url_for('.crawler'))


@admin_bp.route('/category')
@admin_required
def category():
    page = request.args.get('page', 1, type=int)
    pagination = Category.query.order_by(Category.id).paginate(page, per_page=20)
    categories = pagination.items
    return render_template('admin/category.html', categories=categories, pagination=pagination)


@admin_bp.route('/category/add', methods=['GET', 'POST'])
@admin_required
def category_add():
    form = CategoryForm()
    if form.validate_on_submit():
        repeat = Category.query.filter_by(title=form.title.data).first()
        if repeat:
            return redirect(url_for('.category'))
        new_category = Category(title=form.title.data)
        db.session.add(new_category)
        db.session.commit()
        return redirect(url_for('.category'))
    return render_template('admin/category_edit.html', form=form)


@admin_bp.route('/category/edit/<int:category_id>', methods=['GET', 'POST'])
@admin_required
def category_edit(category_id):
    old_category = Category.query.get_or_404(category_id)
    form = CategoryForm()
    if form.validate_on_submit():
        old_category.title = form.title.data
        db.session.commit()
    form.title.data = old_category.title
    return render_template('admin/category_edit.html', form=form)


@admin_bp.route('/category/delete/<int:category_id>', methods=['POST'])
@admin_required
def category_delete(category_id):
    old_category = Category.query.get_or_404(category_id)
    db.session.delete(old_category)
    db.session.commit()
    return redirect_back()


@admin_bp.route('/profile/<int:user_id>', methods=['GET', 'POST'])
@admin_required
def profile(user_id):
    form = UserEditForm()
    user = User.query.get_or_404(user_id)
    if form.validate_on_submit():
        user.username = form.username.data
        user.email = form.email.data
        if form.password.data:
            user.set_password(form.password.data)
        db.session.commit()
        return redirect(url_for('admin.user'))
    form.username.data = user.username
    form.email.data = user.email
    return render_template('admin/profile_popup.html', user=user, form=form)


@admin_bp.route('/delete_user/<user_id>', methods=['POST'])
@admin_required
def delete_user(user_id):
    user = User.query.get_or_404(user_id)
    db.session.delete(user)
    db.session.commit()
    return redirect_back()


@admin_bp.route('/tasks')
@admin_required
def tasks():
    jobs = scheduler.get_jobs()
    return render_template('admin/tasks.html', jobs=jobs)


@admin_bp.route('/task/switch/<job_id>')
@admin_required
def task_switch(job_id):
    old_job = scheduler.get_job(id=job_id)
    if old_job.pending:
        scheduler.pause_job(id=job_id)
    else:
        scheduler.resume_job(id=job_id)
    return redirect(url_for('admin.tasks'))


@admin_bp.route('/task/delete/<job_id>', methods=['POST'])
@admin_required
def task_delete(job_id):
    old_job = scheduler.get_job(id=job_id)
    if old_job:
        scheduler.remove_job(id=job_id)
    return redirect(url_for('.tasks'))
